home *** CD-ROM | disk | FTP | other *** search
- /*
- * ***************
- * * X R F 2 . C *
- * ***************
- *
- * This file contains the identifier tree and reference list management
- * things. It uses a simple binary tree to store the identifiers for
- * lookup and later sorted printing. Each node in the id tree has a
- * pointer to the id string, left and right links and pointers to the
- * beginning and end of the linked list of reference nodes for that
- * id. Only the root of the tree is global, it is used by the sorted
- * index printing function 'prtree'.
- *
- * Version V1.3 9-May-80
- * Version V1.4 10-Jul-80 MM Bummed coe
- * Version V1.5 23-Jul-80 MM Redid storage code
- * Version V1.6 23-Dec-80 RBD Fixed bug in myalloc()
- * Version V1.7 8-Jan-85 MC Document key change for non
- * case-sensitive keys/concatanation.
- * Version V1.17 29-Mar-85 MC write tree to disk if no core
- */
-
- #include <stdio.h>
- #include "xrf.h"
-
- /*
- * Tree search and insertion. This function returns a pointer to
- * the new node if created. This may require some head scratching
- * (I had to!). Look particularly at the significance of the pointer
- * that is returned and how it is used by the recursive caller. If
- * you want more, read "Algorithms + Data Structures = Programs"
- * by Niklaus Wirth (Prentice Hall ISBN 0-13-022418-9) Chapter 4.
- *
- * It searches through the tree for a match to the supplied id (*kp).
- * If it is found, a new reference node is linked into the list for
- * that id. If no match is found, a new is node is inserted into the
- * tree and appropriately initialized, including a first reference
- * node.
- *
- * The node is now positioned in the tree in case non-sensitive order.
- * This means that in the final list mixed, upper & lower case symbols
- * appear togethor instead of being separated in the collating sequence.
- * Also the source name is present for file concatanation.
- *
- * The id (*kp) now comes as <KEYactualNNNNNNNN> from XRF0.C where:-
- * KEY is the symbol as lower case
- * length CPS characters.
- * actual is the symbol as she appears
- * length CPS characters.
- * NNNNNNNN is the program name
- * length 8 chars
- *
- */
-
- static int memfull =0;
-
- struct idt *search(kp, link) /* Function "search" */
- struct idt *link; /* Pointer to id node in tree */
- char *kp; /* Pointer to key string */
- { struct id *n,*placenode();
- memfull =0;
- n=placenode(kp, link); /* insert new ref */
- if(memfull)return NULL; /* if can't, flag NO CORE */
- return n; /* else return new root */
- }
- static struct idt *placenode(kp, link) /* Function "placenode" */
- struct idt *link; /* Pointer to id node in tree */
- char *kp; /* Pointer to key string */
- { struct idt *l; /* Fast tree pointer */
- struct ref *r; /* Fast list pointer */
- struct ref *newref(); /* Make reference function */
- int cond; /* Condition from strcmp */
- char *malloc();
- l = link; /* Copy link into register */
- if(l == NULL){ /* Not found, insert new id node */
- if((l=(struct idt *)malloc(sizeof(struct idt)))==NULL){
- memfull++;
- return NULL;
- } /* Get string space if can*/
- if((l->keyp = malloc(strlen(kp)+1))==NULL){
- free(l);
- memfull++;
- return NULL;
- }
- /* Fill in pointer to ... */
- strcpy(l->keyp, kp); /* ... stashed key string */
- l->left = l->right = NULL; /* No children */
- if((r = newref())==NULL){ /* Attach it to the id node */
- free(l->keyp);
- free(l);
- memfull++;
- return NULL;
- }
- l->last = l->first = r;
- namcnt++;
- refcnt++;
- }
- else if((cond = strcmp(kp, l->keyp)) == 0){ /* Match if true */
- if((r = newref())==NULL){ /* Get a new ref. node */
- memfull++;
- return(l); /* can't */
- }
- l->last->next = r; /* Hook new node into the list */
- l->last = r;
- refcnt++;
- }
- else if(cond < 0) /* Look left */
- l->left = placenode(kp, l->left);
- else /* Look right */
- l->right = placenode(kp, l->right);
- return(l);
- }
-
-
- /*
- * Initialize a line number referece
- */
-
- static struct ref*
- newref()
- { char *malloc();
- struct ref *r;
- if((r = (struct ref *)malloc(sizeof(struct ref)))==NULL)
- return NULL; /* Make a reference node */
- r->lno = lineno; /* Fill in line no. of ref. */
- r->next = NULL; /* This is the end for now */
- return(r); /* Return pointer to the node */
- }
-
- /*--------------------------------------------*/
- /* return all storage to system */
- /*--------------------------------------------*/
- myfree(base) /*WARNING will not update 'base' pointer */
- struct idt *base;
- { struct idt *delidt();
- delidt(base);
- }
-
- struct idt *delidt(link)
- struct idt *link;
- { struct idt *next;
- if (link != NULL){
- link->left=delidt(link->left); /* Visit the left */
- link->right=delidt(link->right); /* Visit the right */
- if(link->left==NULL&&link->right==NULL){ /* no children, so ... */
- delrefs(link->first); /* .. remove refs */
- free(link->keyp); /* .. kill key store */
- free(link); /* .. return space */
- return NULL; /* .. update parent */
- }
- }
- return NULL; /* this went nowhere */
-
- }
- delrefs(link)
- struct ref *link;
- { struct ref *p;
- while(link!=NULL){
- p=link;
- link=link->next;
- free(p);
- }
- }
-
- /*
- * 'quit' handles dynamic memory deficit. (Sounds like U.S. Government!).
- * It issues a polite message to the user, marks the list file for delete
- * and exits to RSX.
- *
- */
-
- quit()
- { abort("Not enough memory space, sorry.\n"); }